package jmine.tec.database.query;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;

import org.hibernate.jdbc.Work;

/**
 * Loader de chaves exportadas de uma tabela.
 * 
 * @author lundberg
 */
public class ExportedKeysLoader implements Callable<List<ExportedKey>> {

    private final Database database;

    private final Table referenced;

    /**
     * Construtor
     * 
     * @param database database
     * @param referenced referenced
     */
    public ExportedKeysLoader(Database database, Table referenced) {
        this.database = database;
        this.referenced = referenced;
    }

    /**
     * {@inheritDoc}
     */
    public List<ExportedKey> call() {
        final List<ExportedKey> keys = new ArrayList<ExportedKey>();
        this.database.doWork(new Work() {
            public void execute(Connection connection) throws SQLException {
                String schema = ExportedKeysLoader.this.database.getSchema();
                this.load(keys, connection, schema);
                if (schema != null) {
                    this.load(keys, connection, schema.toUpperCase());
                }
            }

            /**
             * @param keys keys
             * @param connection connection
             * @param schema schema
             * @throws SQLException SQLException
             */
            private void load(final List<ExportedKey> keys, Connection connection, String schema) throws SQLException {
                ResultSet rs = null;
                try {
                    rs = connection.getMetaData().getExportedKeys(null, schema, ExportedKeysLoader.this.referenced.getName());
                    ExportedKey key = null;
                    int lastSeq = Integer.MAX_VALUE;
                    while (rs.next()) {
                        int seq = rs.getInt("KEY_SEQ");
                        if (seq <= lastSeq) {
                            if (key != null) {
                                keys.add(key);
                            }
                            String referencingTableName = rs.getString("FKTABLE_NAME");
                            Table referencing = ExportedKeysLoader.this.database.findTable(referencingTableName);
                            key = new ExportedKey(ExportedKeysLoader.this.referenced, referencing);
                        }
                        String referencingColumn = rs.getString("FKCOLUMN_NAME");
                        String referencedColumn = rs.getString("PKCOLUMN_NAME");
                        key.addReference(referencedColumn, referencingColumn);
                    }
                    if (key != null) {
                        keys.add(key);
                    }
                } finally {
                    DatabaseUtil.closeQuietly(rs);
                }
            }
        });
        return keys;
    }

}
